﻿namespace DL.UI
{
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class PageParam : IDictionary<string, object>
    {
        private readonly Dictionary<string, object> _hash;

        public PageParam(int num)
        {
            _hash = new Dictionary<string, object>(num);
        }

        public PageParam()
        {
            _hash = new Dictionary<string, object>();
        }

        public PageParam StripKeysWithNullValues()
        {
            var keys = new string[_hash.Count];
            var i = 0;
            foreach (var k in _hash.Keys)
            {
                keys[i++] = k;
            }

            foreach (var key in keys)
            {
                if (_hash[key] == null)
                {
                    _hash.Remove(key);
                }
            }

            return this;
        }

        public ICollection<string> Keys
        {
            get { return _hash.Keys; }
        }

        public ICollection<object> Values
        {
            get { return _hash.Values; }
        }


        public void MergeStringKeys(PageParam addHash)
        {
            if (addHash == null || addHash == this)
            {
                return;
            }

            foreach (var key in addHash.Keys)
            {
                this[key] = addHash[key];
            }
        }


        public bool ContainsKey(string key)
        {
            return this[key] != null;
        }


        public int Count
        {
            get { return _hash.Count; }
        }

        public bool IsReadOnly
        {
            get { return ((ICollection<KeyValuePair<string, object>>)_hash).IsReadOnly; }
        }

        public void Add(string key, object value)
        {
            this[key] = value;
        }

        public bool Remove(string key)
        {
            return _hash.ContainsKey(key) && _hash.Remove(key);
        }

        public bool TryGetValue(string key, out object value)
        {
            value = null;
            if (ContainsKey(key))
            {
                value = _hash[key];
                return true;
            }

            return false;
        }

        public void Add(KeyValuePair<string, object> item)
        {
            ((ICollection<KeyValuePair<string, object>>)_hash).Add(item);
        }

        public bool Remove(KeyValuePair<string, object> item)
        {
            return ((ICollection<KeyValuePair<string, object>>)_hash).Remove(item);
        }

        public void Clear()
        {
            _hash.Clear();
        }


        public bool Contains(KeyValuePair<string, object> item)
        {
            return ((ICollection<KeyValuePair<string, object>>)_hash).Contains(item);
        }

        public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
        {
            ((ICollection<KeyValuePair<string, object>>)_hash).CopyTo(array, arrayIndex);
        }


        public static PageParam Hash(params object[] args)
        {
            if (args.Length % 2 != 0)
            {
                Debug.LogError("Hash requires an even number of arguments!");
                return null;
            }
            else
            {
                var hashTable = new PageParam(args.Length / 2);
                var i = 0;
                while (i < args.Length - 1)
                {
                    var key = (string)args[i];
                    var val = args[i + 1];
                    hashTable[key] = val;
                    i += 2;
                }

                return hashTable;
            }
        }

        public static implicit operator PageParam(Hashtable data)
        {
            var pageData = new PageParam(data.Count);
            foreach (var item in data.Keys)
            {
                pageData.Add(item.ToString(), data[item]);
            }

            return pageData;
        }

        public object this[string key]
        {
            get { return _hash.ContainsKey(key) ? _hash[key] : null; }
            set { _hash[key] = value; }
        }


        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
        {
            return _hash.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public T TryGet<T>(string key, T defaultValue = default(T))
        {
            if (!_hash.TryGetValue(key, out object value))
            {
                return defaultValue;
            }

            return (T)value;
        }

        public T TryPopGet<T>(string key, T defaultValue = default(T))
        {

            if (_hash.ContainsKey(key))
            {
                var val = _hash[key];
                _hash.Remove(key);
                return (T)val;
            }

            return defaultValue;
        }
    }
}